﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Phone.Info;
using RGBFinder.Resources;


namespace RGBFinder
{
    public class Score
    {
        public string name;
        public string time;
        public int tests;
        public int score;

        public Score()
        {
            name="";
            time="";
            tests=0;
            score=0;
        }
    }

    public static class Scoreboard
    {

        public static List<Score> LoadScores()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("Scores.xml", FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(List<Score>));
                        using (var reader = new StreamReader(streamFile))
                            return serializer.Deserialize(reader) as List<Score>;
                    }
                    catch (Exception) { return new List<Score>(); }
                }
            }
        }

        public static void DeleteScores()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("Scores.xml");
            }
        }

        public static void SaveScores(List<Score> state)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("Scores.xml");
                using (var streamFile = appStorage.OpenFile("Scores.xml", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                //write_options_state(writer, entry);
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(List<Score>));
                    serializer.Serialize(writer, state);
                }
            }
        }

        public static void AddScore(Score score)
        {
            var list = LoadScores();

            var ok = false;

            for(int i=0;i<list.Count;i++)
                if (list[i].name == score.name && list[i].score == score.score && list[i].tests == score.tests && list[i].time == score.time)
                    return;
            for (int i = 0; i < list.Count; i++)
            {
                
                if (list[i].score < score.score)
                {
                    ok = true;
                    list.Insert(i, score);
                    break;
                }
            }
            if (!ok)
                list.Add(score);
            if(list.Count>=10)
            {
                var newList = new List<Score>();
                for (int i = 0; i < 10; i++)
                    newList.Add(list[i]);
                list = newList;
            }

            SaveScores(list);
        }

        public static Byte[] CreateMD5Hash(string input)
        {
            var hashalg = new SHA256Managed();
            var h = hashalg.ComputeHash(Encoding.UTF8.GetBytes(input));
            return h;
        }

        public static string GetHashString(string input)
        {

            System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();

            var hashalg = new SHA256Managed();
            var h = hashalg.ComputeHash(Encoding.UTF8.GetBytes(input));

            byte[] hash = hashalg.ComputeHash(enc.GetBytes(input));
            string output = Convert.ToBase64String(hash);
            return output;



            /*
            byte[] textBytes = System.Text.Encoding.UTF8.GetBytes(input);
            try
            {
                var hashalg = new SHA1Managed();
                //var h = hashalg.ComputeHash(Encoding.UTF8.GetBytes(input));
                byte[] hash = hashalg.ComputeHash(textBytes);
                string ret = "";
                foreach (byte a in hash)
                {
                    if (a < 16)
                        ret += "0" + a.ToString("x");
                    else
                        ret += a.ToString("x");
                }
                return ret;
            }
            catch
            {
                return "";
            }
            */


        }

        

        public static int ComputeScore(GameStatus status)
        {
            
            var score = 1000000;
            var t = status.tests;
            if (t <= 0)
                t = 1;
            score = score / t;
            var sec = (int)status.timer.TotalSeconds;
            if (sec <= 0)
                sec = 1;
            score = score / sec;

            switch (status.difficulty)
            {
                case GameDifficulty.Easy:
                    score = score / 10;
                    break;
                case GameDifficulty.Hard:
                    score = score * 10;
                    break;
                case GameDifficulty.Alpha:
                    score = score * 15;
                    break;
                case GameDifficulty.Reverse:
                    score = score * 20;
                    break;
                default:

                    break;
            }
            return score;
        }

        public static void getHTML(string query, string options, Action<string> callback, Action<string, string> callback2, Action error)
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(query);
                req.Method = "GET";
                req.BeginGetResponse(
                    (asyncResult) =>
                    {
                        try
                        {
                            HttpWebResponse objResponse = null;
                            StreamReader objs = null;

                            HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;

                            objResponse = (HttpWebResponse)request.EndGetResponse(asyncResult);
                            objs = new StreamReader(objResponse.GetResponseStream());

                            var s = objs.ReadToEnd();
                            if (callback2 != null)
                                callback2(s, options);
                            else if (callback != null)
                                callback(s);

                            return;
                        }
                        catch (Exception)
                        {
                            error();
                        }
                    }
                    , req);
            }
            catch (Exception)
            {
                error();
            }
        }
        public static void getHTML(string query, Action<string> callback, Action error)
        {
            getHTML(query, "", callback, null, error);
        }


        public static void getHTML(string query, string options, Action<string, string> callback, Action error)
        {
            getHTML(query, options, null, callback, error);
        }

        public static string GetUtilizationUrl(bool isTrial)
        {
            return GetUtilizationUrl(0, isTrial);
        }
        public static string GetUtilizationUrl(int occ, bool isTrial)
        {
            
            var s = "http://fboscari.altervista.org/submit_Utilizzi.php?name=" +
                Strings.Title +
                (isTrial?" Trial":"") +
                "&id=" +
                getID();
            if (occ >= 1)
                s += "&occ=" +
                    occ;
            return s; 

        }
        public static string getID()
        {
            byte[] result = null;
            object uniqueId;
            if (DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out uniqueId))
                result = (byte[])uniqueId;
            var s = "";
            for (int i = 0; i < result.Length; i++)
                s += result[i];
            return s;
        }


        #region utilizations
        private static Func<StreamReader, int> read_utilizations = reader =>
        {

            var s = reader.ReadToEnd();
            var occ = Int16.Parse(s);

            
            return occ;
        };
        

        private static Action<StreamWriter, int> write_utilizations = (writer, occ) =>
        {
            var s = "" + occ;
            
            writer.Write(s);
        };



        public static void SaveUtilizations(int utilizations)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("utilizations.txt");
                using (var streamFile = appStorage.OpenFile("utilizations.txt", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                    write_utilizations(writer, utilizations);
            }
        }

        

        public static void DeleteUtilizations()
        {
            var appStorage = IsolatedStorageFile.GetUserStoreForApplication();
            appStorage.DeleteFile("utilizations.txt");
        }

        public static int LoadUtilizations()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("utilizations.txt", FileMode.OpenOrCreate))
                {
                    try
                    {
                        using (var reader = new StreamReader(streamFile))
                            return read_utilizations(reader);
                    }
                    catch (Exception) {
                        appStorage.DeleteFile("utilizations.txt");
                        return 0;
                    }
                }

                
            }

        }
        #endregion
    }
}
